package org.linlinjava.litemall.admin.service2;

import com.github.pagehelper.PageHelper;
import org.linlinjava.litemall.admin.web2.order.resp.OResp8;
import org.linlinjava.litemall.admin.web2.user.req.UReq1;
import org.linlinjava.litemall.admin.web2.user.req.UReq2;
import org.linlinjava.litemall.admin.web2.user.req.UReq3;
import org.linlinjava.litemall.admin.web2.user.req.UReq4;
import org.linlinjava.litemall.admin.web2.user.resp.*;
import org.linlinjava.litemall.core.util.DateTimeUtil;
import org.linlinjava.litemall.core.util.R;
import org.linlinjava.litemall.core.util.Util;
import org.linlinjava.litemall.db.dao.LitemallAdminMapper;
import org.linlinjava.litemall.db.dao.TFansMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.enumeration.Const;
import org.linlinjava.litemall.db.util.Str;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.persistence.Query;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
public class AUserService extends ABaseService {

    private static Logger log = LoggerFactory.getLogger(AUserService.class);

    @Autowired
    private LitemallAdminMapper adminMapper;
    @Autowired
    private TFansMapper fansMapper;


    public List<OResp8> getSendPerson() {
        List<LitemallAdmin> admins = adminMapper.selectByExample(LitemallAdminExample.newAndCreateCriteria().andSendManagerEqualTo(Boolean.TRUE).example());
        List<OResp8> res = Util.aList(admins.size());
        admins.forEach(admin -> res.add(new OResp8(admin)));
        return res;
    }

    public List<UResp1> getShop(List<Integer> identities) {
        List<TShop> allShop = shopMapper.selectByExample(TShopExample.newAndCreateCriteria().andIdentityIn(identities).example());
        List<UResp1> resList = Util.aList(allShop.size());
        allShop.forEach(s -> {
            UResp1 vo = new UResp1();
            vo.setId(s.getId());
            vo.setName(s.getShopName());
            resList.add(vo);
        });
        return resList;
    }

    public Object allUserList(String name, String phone, Integer page, Integer size, Integer belongDirectId) {
        List<TUser2> userList = getUserList(name, phone, page, size, null, belongDirectId);
        List<UResp6> voList = Util.aList(userList.size());

        Map<Integer, UResp6> voMap = Util.hMap();
        StringBuilder ids = Str.sb();
        userList.forEach(u -> {
            Integer id = u.getId();
            UResp6 vo = new UResp6();
            vo.setId(id);
            vo.setName(u.getName());
            vo.setCode(u.getCode());
            vo.setPhone(u.getPhone());
            vo.setBalance(u.getBalance().toString());
            TUserInfo info = findUserInfoByUser2Id(id);
            if (info != null) {
                vo.setImg(info.getAvatar());
            }
            vo.setCreateTime(u.getCreatedTime().format(DateTimeUtil.format));
            vo.setRoleName(Const.Identity.value(u.getIdentity()));
            voList.add(vo);
            ids.append(id).append(",");
            voMap.put(u.getId(), vo);
        });
        ids.delete(ids.length() - 1, ids.length());

        Query query = query("select u_id,sum(1),sum(pay_amount) from t_order where order_status in (1,2,3,4) AND u_id in (" + ids + ") group by u_id ");
        List<Object[]> list = query.getResultList();
        list.forEach(o -> {
            Integer id = Integer.parseInt(o[0].toString());
            UResp6 vo = voMap.get(id);
            if (vo != null) {
                vo.setBuyCount(o[1].toString());
                vo.setBuyAmount(o[2].toString());
            }
        });
        return R.okList(voList);
    }

    /**
     * 个人团长列表
     *
     * @param name
     * @param page
     * @param size
     * @param beginDate
     * @param endDate
     * @return
     */
    public Object distributorList(String name, String phone, Integer page, Integer size, String beginDate, String endDate, Integer belongDirectId) {
        List<TUser2> userList = getUserList(name, phone, page, size, Const.Identity.DISTRIBUTOR, belongDirectId);

        List<UResp3> voList = Util.aList(userList.size());
        if (userList.size() == 0)
            return R.okList(voList, userList);

        Map<Integer, UResp3> voMap = Util.hMap();
        StringBuilder ids = Str.sb();
        userList.forEach(u -> {
            Integer id = u.getId();
            UResp3 vo = new UResp3();
            vo.setId(id);
            vo.setName(u.getName());
            TShop shop = findShopByUser2Id(id);
            if (shop != null) {
                vo.setShopAddress(shop.getAddress());
                ids.append(id).append(",");
            } else {
                log.error("数据异常[id={}]", id);
            }
            voMap.put(id, vo);
            voList.add(vo);
        });
        ids.delete(ids.length() - 1, ids.length());
        log.info("开始统计分销数据");
        StringBuilder sb = Str.sb("select u_id ,sum(if(type=1,total_amount,0)) ,sum(if(type=1,1,0)),sum(if(type=1,amount,0)),sum(total_amount),sum(if(type=2,amount,0)),sum(if(type=3,amount,0)) " +
                " from t_money_record where 1=1 AND u_id in (:uId) ");
        if (!Str.isEmpty(beginDate))
            sb.append(" AND created_time >= :beginDate");
        if (!Str.isEmpty(endDate))
            sb.append(" AND created_time < :endDate");
        sb.append(" group by u_id ");
        Query query = query(sb.toString());
        if (!Str.isEmpty(beginDate))
            query.setParameter("beginDate", beginDate);
        if (!Str.isEmpty(endDate))
            query.setParameter("endDate", endDate);
        query.setParameter("uId", ids.toString());
        List<Object[]> list = query.getResultList();
        list.forEach(o -> {
            Integer id = Integer.parseInt(o[0].toString());
            UResp3 vo = voMap.get(id);
            vo.setSaleAmount(o[1].toString());
            vo.setSaleCount(o[2].toString());
            vo.setSaleCom(o[3].toString());
            vo.setTotalAmount(o[4].toString());
            vo.setFansAmount(o[5].toString());
            vo.setFans2Amount(o[6].toString());
        });

        setFans(ids.toString(), voMap);

        return R.okList(voList, userList);
    }

    /**
     * 提货团长
     */
    public Object selfmentionList(String name, String phone, Integer page, Integer size, String beginDate, String endDate, Integer belongDirectId) {
        List<TUser2> userList = getUserList(name, phone, page, size, Const.Identity.SELFMENTION, belongDirectId);

        List<UResp4> voList = Util.aList(userList.size());
        if (userList.size() == 0)
            return R.okList(voList, userList);

        Map<Integer, UResp4> voMap = Util.hMap();
        List<String> ids = Util.aList();
        userList.forEach(u -> {
            Integer id = u.getId();
            UResp4 vo = new UResp4();
            vo.setId(id);
            TShop shop = findShopByUser2Id(id);
            if (shop != null) {
                vo.setShopAddress(shop.getAddress());
                vo.setName(shop.getShopName());
                ids.add(id + "");
            } else {
                log.error("数据异常[id={}]", id);
            }
            voMap.put(id, vo);
            voList.add(vo);
        });
        log.info("开始统计分销数据");
        StringBuilder sb = Str.sb("select u_id ,sum(if(type=1,total_amount,0)) ,sum(if(type=1,1,0)),sum(if(type=1,amount,0))," +
                "sum(total_amount),sum(if(type=2,amount,0)),sum(if(type=3,amount,0)) ,sum(if(type=4,amount,0)),sum(if(type=5,amount,0))" +
                " from t_money_record where 1=1 AND u_id in (:uId) ");
        if (!Str.isEmpty(beginDate))
            sb.append(" AND created_time >= :beginDate");
        if (!Str.isEmpty(endDate))
            sb.append(" AND created_time < :endDate");
        sb.append(" group by u_id ");
        Query query = query(sb.toString());
        if (!Str.isEmpty(beginDate))
            query.setParameter("beginDate", beginDate);
        if (!Str.isEmpty(endDate))
            query.setParameter("endDate", endDate);

        query.setParameter("uId", String.join(",", ids));
        List<Object[]> list = query.getResultList();
        list.forEach(o -> {
            Integer id = Integer.parseInt(o[0].toString());
            UResp4 vo = voMap.get(id);
            vo.setSaleAmount(o[1].toString());
            vo.setSaleCount(o[2].toString());
            vo.setSaleCom(o[3].toString());
            vo.setTotalAmount(o[4].toString());
            vo.setFansAmount(o[5].toString());
            vo.setFans2Amount(o[6].toString());
            vo.setPickUpCom(o[7].toString());
            vo.setSendAmount(o[8].toString());

        });

        setFans(ids.toString(), voMap);
        return R.okList(voList, userList);
    }


    /**
     * 加盟店和特殊加盟店
     */
    public Object franshisedList(String name, String phone, Integer page, Integer size, String beginDate, String endDate, Integer identity, Integer belongDirectId) {
        List<TUser2> userList = getUserList(name, phone, page, size, identity, belongDirectId);

        List<UResp5> voList = Util.aList(userList.size());
        if (userList.size() == 0)
            return R.okList(voList, userList);

        Map<Integer, UResp5> voMap = Util.hMap();
        StringBuilder ids = Str.sb();
        userList.forEach(u -> {
            Integer id = u.getId();
            UResp5 vo = new UResp5();
            vo.setId(id);
            TShop shop = findShopByUser2Id(id);
            if (shop != null) {
                vo.setShopAddress(shop.getAddress());
                vo.setName(shop.getShopName());
                ids.append(id).append(",");
            } else {
                log.error("数据异常[id={}]", id);
            }
            voMap.put(id, vo);
            voList.add(vo);
        });
        ids.delete(ids.length() - 1, ids.length());
        log.info("开始统计分销数据");
        StringBuilder sb = Str.sb("select u_id ,sum(if(type=1,total_amount,0)) ,sum(if(type=1,1,0)),sum(if(type=1,amount,0))," +
                "sum(total_amount),sum(if(type=2,amount,0)),sum(if(type=3,amount,0)) ,sum(if(type=4,amount,0)),sum(if(type=5,amount,0))," +
                "sum(if(type=0,amount,0)),sum(if(type=6,amount,0)),sum(if(type=7,amount,0)), sum(if(type=8,amount,0))" +
                " from t_money_record where 1=1 AND u_id in (:uId) ");
        if (!Str.isEmpty(beginDate))
            sb.append(" AND created_time >= :beginDate");
        if (!Str.isEmpty(endDate))
            sb.append(" AND created_time < :endDate");
        sb.append(" group by u_id ");
        Query query = query(sb.toString());
        if (!Str.isEmpty(beginDate))
            query.setParameter("beginDate", beginDate);
        if (!Str.isEmpty(endDate))
            query.setParameter("endDate", endDate);
        query.setParameter("uId", ids.toString());
        List<Object[]> list = query.getResultList();
        list.forEach(o -> {
            Integer id = Integer.parseInt(o[0].toString());
            UResp5 vo = voMap.get(id);
            vo.setSaleAmount(o[1].toString());
            vo.setSaleCount(o[2].toString());
            vo.setSaleCom(o[3].toString());
            vo.setTotalAmount(o[4].toString());
            vo.setFansAmount(o[5].toString());
            vo.setFans2Amount(o[6].toString());
            vo.setPickUpCom(o[7].toString());
            vo.setSendAmount(o[8].toString());

            //加盟店售出     使用红包    红包报销    佣金支出
            vo.setSaleTotalAmount(o[9].toString());
            vo.setUseRed(o[10].toString());
            vo.setBaoxiaoRed(o[11].toString());
            vo.setComPay(o[12].toString());

        });

        setFans(ids.toString(), voMap);
        return R.okList(voList, userList);
    }

    /**
     * 直营店统计
     *
     * @param belongDirectId
     * @return
     */
    public Object directDataList(Integer belongDirectId) {
        List<UResp9> list = Util.aList();
        // 个人团长
        list.add(new UResp9("团长页自然售出"));
        list.add(new UResp9("个人团长售出"));
        list.add(new UResp9("商家团长售出"));
        list.add(new UResp9("加盟店售出"));
        list.add(new UResp9("特殊加盟店售出"));
        list.add(new UResp9("直营店售出"));
        list.add(new UResp9("及时达售出"));
        list.add(new UResp9("总统计"));
        return R.ok(list);
    }
//
//    public UResp9 geRen(Integer belongDirectId) {
//        Query query1 = query("select count(1) from t_user2 where p_id = :pId ");
//        query1.setParameter("pId", belongDirectId);
//        int result = query1.getFirstResult();
//        UResp9 vo = new UResp9();
//        return vo;
//    }

    void setFans(String pIds, Map voMap) {
        log.info("计算粉丝数量");
        Query fansQuery = query("select p_id ,count(if(type=0,1,null)),count(if(type=1,1,null)) from t_fans where p_id in(:pId) group by p_id");
        fansQuery.setParameter("pId", pIds);
        List<Object[]> blist = fansQuery.getResultList();
        blist.forEach(o -> {
            Integer id = Integer.parseInt(o[0].toString());
            UResp vo = (UResp) voMap.get(id);
            vo.setFans1(o[1].toString());
            vo.setFans2(o[2].toString());
        });
    }

    List<TUser2> getUserList(String name, String phone, Integer page, Integer size, Integer identity, Integer belongDirectId) {
        PageHelper.startPage(page, size);
        List<TUser2> userList = user2Mapper.selectByExample(TUser2Example.newAndCreateCriteria()
                .when(identity != null, c -> c.andIdentityEqualTo(identity))
                .when(!Str.isEmpty(name), c -> c.andNameLike(Str.toLike(name)))
                .when(!Str.isEmpty(phone), c -> c.andPhoneEqualTo(phone))
                .when(belongDirectId != null, c -> c.andBelongDirectIdEqualTo(belongDirectId))
                .example());
        return userList;
    }

    /**
     * 提现审核列表
     */
    public Object cashOutList(String transNo, String phone, Integer page, Integer size, String beginDate, String endDate, Integer status) {
        PageHelper.startPage(page, size);
        List<TWxCashoutApply> list = wxCashoutApplyMapper.selectByExample(TWxCashoutApplyExample
                .newAndCreateCriteria()
                .when(!Str.isEmpty(transNo), c -> c.andTransNoEqualTo(transNo))
                .when(!Str.isEmpty(phone), c -> c.andPhoneEqualTo(phone))
                .when(!Str.isEmpty(beginDate), c -> c.andCreatedTimeGreaterThanOrEqualTo(DateTimeUtil.formatYYYY_MM_DD(beginDate)))
                .when(!Str.isEmpty(endDate), c -> c.andCreatedTimeLessThan(DateTimeUtil.formatYYYY_MM_DD(endDate)))
                .when(status != null, c -> c.andStatusEqualTo(status))
                .example().orderBy("created_time desc"));
        List<UResp7> voList = Util.aList(list.size());
        list.forEach(e -> voList.add(new UResp7(e)));
        return R.okList(voList, list);
    }

    public Object saveWxCashOutApply(@RequestBody UReq2 req) {
        TWxCashoutApply apply = wxCashoutApplyMapper.selectByPrimaryKey(req.getId());
        if (apply.getStatus() != 0) {
            return R.fail("已经审核过了");
        }
        apply.setDescription(req.getDescription());
        apply.setPayNo(req.getPayNo());
        apply.setStatus(req.getStatus());
        wxCashoutApplyMapper.updateByPrimaryKey(apply);
        if (req.getStatus() == 2) {
            log.info("提现订单[transNo={}]未通过，退还金额", apply.getTransNo());
            TUser2 user = user2Mapper.selectByPrimaryKey(apply.getUserId());
            user.setBalance(user.getBalance().add(apply.getAmount()));
            user.setUpdateTime(LocalDateTime.now());
            user2Mapper.updateByPrimaryKey(user);
        }
        return R.ok();
    }

    /**
     * 保存审核
     *
     * @param req
     * @return
     */
    public Object saveApply(UReq1 req) {
        Integer id = req.getId();
        TShopApply apply = shopApplyMapper.selectByPrimaryKey(id);
        if (apply.getStatus() != Const.APPLY_STATUS.WAIT) {
            return R.fail("已经审核过了，操作失败!");
        }
        Integer opt = req.getOpt();
        if (opt != Const.APPLY_STATUS.SUCCESS && opt != Const.APPLY_STATUS.FAIL) {
            return R.fail("不支持的审核类型");
        }
        if (opt == Const.APPLY_STATUS.FAIL) {
            apply.setStatus(Const.APPLY_STATUS.FAIL);
            shopApplyMapper.updateByPrimaryKey(apply);
            return R.ok();
        }
        apply.setStatus(Const.APPLY_STATUS.SUCCESS);
        log.info("审核通过");
        TUser2 user = user2Mapper.selectByPrimaryKey(apply.getUserId());
        if (req.getpId() != null)
            user.setBelongDirectId(req.getpId());
        if (!Str.isEmpty(apply.getCode())) {
            log.info("修改用户[id={}]的提成上级");
            TUser2 pUser = findUserByCode(apply.getCode());
            if (pUser != null)
                user.setpId(pUser.getId());
        }
        TShop shop;
        if (apply.getType() == Const.APPLY_TYPE._0) {
            log.info("用户[id={}]升级为个人团长", user.getId());
            user.setIdentity(Const.Identity.DISTRIBUTOR);
            shop = initShop(user, apply);
            user.setsId(shop.getId());
        } else {
            log.info("用户[id={}]升级为提货团长", user.getId());
            user.setIdentity(req.getTypeCode());
            shop = initShop(user, apply);
            user.setsId(shop.getId());
            if (user.getIdentity() == Const.Identity.FRANSHISED2 || user.getIdentity() == Const.Identity.DIRECT) {
                log.info("用户[id={}]升级为特殊加盟店团长或直营店、取消提成上级和归属上级", user.getId());
                user.setBelongDirectId(null);
                user.setpId(null);
            }
            shop = initShop(user, apply);
            user.setsId(shop.getId());
        }
        shopApplyMapper.updateByPrimaryKey(apply);
        shopMapper.updateByPrimaryKeySelective(shop);
        user2Mapper.updateByPrimaryKeySelective(user);
        initFans(user);
        return R.ok("审核成功");
    }


    /**
     * 初始化商户表
     *
     * @param user
     * @return
     */
    private TShop initShop(TUser2 user, TShopApply apply) {
        TShop shop = findShopByUser2Id(user.getId());
        if (shop != null) {
            shop.setIdentity(user.getIdentity());
            shop.setLatitude(apply.getLatitude());
            shop.setLongitude(apply.getLongitude());
            shop.setIsBusiness(Boolean.FALSE);          //默认不营业
            shop.setSendDistance(new BigDecimal(0));  //默认配送范围0
            shop.setCommission(10);                     //默认佣金10
            shop.setShopName(apply.getCommunityName()); //商铺名称
            shop.setAddress(apply.getDetailAddress());  //地址
            shop.setBusinessPhone(apply.getPhone());    //手机
            shop.setDisCount(new BigDecimal(10));   //默认10折
            shop.setLicense(apply.getLicense());
            shop.setOtherLicense(apply.getOtherLicense());
            shop.setUser2Id(user.getId());
            shop.setDeleted(Boolean.FALSE);
            shop.setCreatedTime(LocalDateTime.now());
            shop.setFreeSend(Boolean.FALSE);    //是否包邮：默认否
            shop.setBusinessDate("08:30-18:30");
        } else {
            shop = new TShop();
            shop.setIdentity(user.getIdentity());       //身份
            shop.setLatitude(apply.getLatitude());
            shop.setLongitude(apply.getLongitude());
            shop.setIsBusiness(Boolean.FALSE);          //默认不营业
            shop.setSendDistance(new BigDecimal(0));  //默认配送范围0
            shop.setCommission(10);                     //默认佣金10
            shop.setShopName(apply.getCommunityName()); //商铺名称
            shop.setAddress(apply.getDetailAddress());  //地址
            shop.setBusinessPhone(apply.getPhone());    //手机
            shop.setDisCount(new BigDecimal(10));   //默认10折
            shop.setLicense(apply.getLicense());
            shop.setOtherLicense(apply.getOtherLicense());
            shop.setUser2Id(user.getId());
            shop.setDeleted(Boolean.FALSE);
            shop.setCreatedTime(LocalDateTime.now());
            shop.setFreeSend(Boolean.FALSE);    //是否包邮：默认否
            shop.setBusinessDate("08:30-18:30");
            shopMapper.insert(shop);
            log.info("生成商户表[{}]", shop);
            shop = shopMapper.selectOneByExample(TShopExample.newAndCreateCriteria().andUser2IdEqualTo(user.getId()).example());
        }
        return shop;
    }

    /**
     * 查看商家信息
     *
     * @param id
     * @return
     */
    public Object get(Integer id) {
        TUser2 user = user2Mapper.selectByPrimaryKey(id);
        if (user == null) {
            return R.fail("不存在数据");
        }
        TUserInfo userInfo = findUserInfoByUser2Id(id);
        UResp8 vo = new UResp8();
        vo.setId(user.getId());
        vo.setUserImg(userInfo.getAvatar());
        vo.setCreatedTime(user.getCreatedTime().format(DateTimeUtil.format));
        vo.setName(user.getName());
        vo.setWxOpenid(userInfo.getWeixinOpenid());
        vo.setPhone(user.getPhone());
        if (user.getpId() != null) {
            TUser2 p = user2Mapper.selectByPrimaryKey(user.getpId());
            vo.setCode(p.getCode() + "(" + p.getName() + ")");
        }
        TShop shop = findShopByUser2Id(id);
        if (shop != null) {
            vo.setShopName(shop.getShopName());
            vo.setLicense(shop.getLicense());
            vo.setOtherLicense(shop.getOtherLicense());
        } else {
            log.error("用户[id={}]数据异常，没有shop表数据");
        }
        vo.setShareCode(user.getCode());
        vo.setRoleName(Const.Identity.value(user.getIdentity()));
        vo.setBelongDirectId(user.getBelongDirectId());
        return R.ok(vo);
    }

    /**
     * 保存商家信息
     *
     * @param req
     * @return
     */
    @Transactional
    public Object save(UReq3 req) {
        String msg = "修改成功";
        TUser2 user = user2Mapper.selectByPrimaryKey(req.getId());
        TShop shop = findShopByUser2Id(req.getId());
        user.setBelongDirectId(req.getBelongDirectId());
        if (user.getIdentity() != Const.Identity.DISTRIBUTOR) {
            user.setIdentity(Const.Identity.type(req.getRoleName()));
            shop.setIdentity(Const.Identity.type(req.getRoleName()));

            user.setUpdateTime(LocalDateTime.now());
            user2Mapper.updateByPrimaryKey(user);
            shopMapper.updateByPrimaryKey(shop);
        } else {
            if (!"个人团长".equalsIgnoreCase(req.getRoleName())) {
                msg = "个人团长资料不全，无法修改成其他角色";
            }
            log.info(msg);
        }
        return R.ok(msg);
    }

    /**
     * 初始化粉丝
     *
     * @param user
     */
    private void initFans(TUser2 user) {
        log.info("初始化粉丝");
        if (user.getpId() != null) {
            log.info("当前用户[{}]成为[{}]的提成下级粉丝", user.getId(), user.getpId());
            TFans fans = TFans.builder().createdTime(LocalDateTime.now()).uId(user.getId()).pId(user.getpId()).amount(new BigDecimal(0)).build();
            TUserInfo userInfo = findUserInfoByUser2Id(user.getId());
            fans.setUserImg(userInfo.getAvatar());
            fans.setUserName(user.getName());
            if (user.getIdentity() == Const.Identity.DISTRIBUTOR) {
                log.info("成为个人团长粉丝");
                fans.setType(0);
            } else {
                log.info("成为提货团长粉丝");
                fans.setType(1);
            }
            fansMapper.insert(fans);
        }
    }

    /**
     * 删除团长
     * @param req
     * @return
     */
    public Object del(UReq4 req) {
        TUser2 shopUser = findUserById(req.getId());
        shopUser.setIdentity(Const.Identity.USER);
        shopUser.setUpdateTime(LocalDateTime.now());
        user2Mapper.updateByPrimaryKey(shopUser);
        return R.ok("删除成功!");
    }
}
